use std::fmt::{Display};

use futures::Sink;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::error::SerdeJsonDeserializeError;
use crate::models::{default_count, default_false};

/// 哔哩哔哩 UP 主
pub const BILI_USER_DDL: &str = r#"
create table if not exists bili_user
(
    mid           INT8,
    uname         TEXT,
    face          TEXT,
    sign          TEXT,
    video_count   INT8,
    audio_count   INT8,
    album_count   INT8,
    article_count INT8,
    deleted       INT8 default 0 not null
);
"#;

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct BiliUserModel  {
    pub mid: i64,
    pub uname: String,
    pub face: String,
    pub sign: String,
    #[serde(default = "default_count")]
    pub video_count: i64,
    #[serde(default = "default_count")]
    pub audio_count: i64,
    #[serde(default = "default_count")]
    pub album_count: i64,
    #[serde(default = "default_count")]
    pub article_count: i64,
    #[serde(default = "default_false")]
    pub deleted: bool,
}

impl TryFrom<&Value> for BiliUserModel {
    type Error = SerdeJsonDeserializeError;

    fn try_from(value: &Value) -> Result<Self, Self::Error> {
        let get_string: fn(&Value) -> Option<String> = |x| {
            let string = x.to_string();
            if string.is_empty() {
                None
            } else {
                Some(string)
            }
        };
        let vals = (
            value.get("mid").and_then(|x| x.as_i64()),
            value.get("uname").and_then(get_string),
            value.get("face").and_then(get_string),
            value.get("sign").and_then(get_string)
        );

        Self {
            mid: value.get("mid").and_then(|x| x.as_i64()).unwrap(),
            uname: value.get("uname").and_then(|x| x.as_str()).unwrap().to_owned(),
            face: value.get("face").unwrap().as_str().unwrap().to_string(),
            sign: value.get("sign").unwrap().as_str().unwrap().to_string(),
            video_count: -1,
            audio_count: -1,
            album_count: -1,
            article_count: -1,
            deleted: false,
        }
    }
}

impl From<Value> for BiliUserModel {
    fn from(value: Value) -> Self { Self::from(&value) }
}

impl BiliUserModel {
    pub fn new(mid: i64, uname: &str, face: &str, sign: &str) -> Self {
        Self {
            mid,
            uname: uname.to_string(),
            face: face.to_string(),
            sign: sign.to_string(),
            video_count: default_count(),
            audio_count: default_count(),
            album_count: default_count(),
            article_count: default_count(),
            deleted: default_false(),
        }
    }
}